if(Fw.TOP_WINDOW){
    Fw.Modal = Fw.TOP_WINDOW.Fw.Modal;
    Fw.Window = Fw.TOP_WINDOW.Fw.Window;
    Fw.Msg = Fw.TOP_WINDOW.Fw.Msg;
}
else{
    /**
     * 弹出窗口
     */
    Fw.Modal = Fw.extend(Fw.Component, {
        /**
         * 默认宽度
         */
        width: 600,
        /**
         * 默认高度
         */
        height: 500,
        /**
         * 是否显示关闭按钮
         */
        closable: true,
        /**
         * 是否显示加载状态
         */
        loadMask: true,
        /**
         * 初始化组件
         */
        initComponent: function(){
            Fw.Modal.superclass.initComponent.call(this);
            if(this.loadMask){
                this.loadMask = new Fw.LoadMask();
            }
        },
        /**
         * 初始化事件
         */
        initEvents: function(){
            //浏览器窗口改变尺寸时触发
            $(window).resize(Fw.bind(this.center, this));
            //窗口显示前触发
            this.on('beforeshow', this.onBeforeshow, this);
            //窗口显示后触发
            this.el.on('shown.bs.modal', Fw.bind(this.onShow, this));
            //窗口隐藏后触发
            this.el.on('hidden.bs.modal', Fw.bind(this.onHide, this));
            //iframe加载完成后触发
            this.iframe.on('load', Fw.bind(this.onLoadIframe, this));
            //
            if(Fw.isTouch && this.el.swipe){
                this.touch = this.el.swipe({
                    swipe: function(e) {
                        e.stopPropagation();
                    }
                }).data('TouchSwipe');
            }
        },
        /**
         * 初始化HTML模版
         */
        initTpl: function(){
            var id = Fw.id();
            var tpl = [
                '<div id="${id}" class="window modal fade">',
                    '<div id="${id}-dialog" class="modal-dialog">',
                        '<div id="${id}-content" class="modal-content">',
                            '<div id="${id}-header" class="modal-header">',
                                '<a id="${id}-closable" optId="close" class="close icon icon-close" data-dismiss="modal"></a>',
                                '<h4 id="${id}-title" class="modal-title"></h4>',
                            '</div>',
                            '<div id="${id}-body" class="modal-body"></div>',
                            '<iframe id="${id}-iframe" class="iframe-body" frameborder="no" scrolling="auto"></iframe>',
                            '<div id="${id}-footer" class="modal-footer"></div>',
                        '</div>',
                    '</div>',
                '</div>'
            ];
            $('body').append(Fw.template(tpl, {
                id: id
            }));
            this.el = $('#' + id);
            this.dialog = $('#' + id + '-dialog');
            this.content = $('#' + id + '-content');
            this.header = $('#' + id + '-header');
            this.titleEl = $('#' + id + '-title');
            this.body = $('#' + id + '-body');
            this.iframe = $('#' + id + '-iframe');
            this.footer = $('#' + id + '-footer');
            this.closableEl = $('#' + id + '-closable');
            //
            var btnTpl = [
                '<button optId="${id}" type="button" class="btn ${cls}" style="${style}" data-dismiss="${dismiss===false ? \"\" : \"modal\"}">${text}</button>',
            ];
            this.btnTpl = Fw.template(btnTpl);
        },
        /**
         * iframe加载完成后触发
         */
        onLoadIframe: function(){
            if(this.iframe.attr('src')){
                var content = this.iframe[0].contentWindow;
            	try{
                    content.App.onShowWindow && content.App.onShowWindow.call(content.App, this);
                }
                catch(e){
                    if(arguments[0] !== false){
                        Fw.defer(this.onLoadIframe, 100, this, [false]);
                    }
                    else{
                        throw e;
                    }
                }
                //
                if(this.loaded !== true && this.loadMask){
                    Fw.defer(this.loadMask.hide, 100, this.loadMask);
                    this.loaded = true;
                }
            }
        },
        /**
         * 隐藏后
         */
        onHide: function(){
            this.hidden = true;
        },
        /**
         * 显示前
         */
        onBeforeshow: function(options){
            var me = this;
            Fw.applyIf(options, {
                closable: this.closable,
                width: this.width,
                height: this.height
            });
            //
            this.titleEl.html(options.title || '&#160;');
            //
            if(options.headerVisible !== false){
                this.header.show();
            }
            else{
                this.header.hide();
            }
            //
            if(options.closable){
                this.closableEl.show();
                if(options.closeHandler){
                    this.closableEl.one('click', function(e){
                        var content = options.html ? null : me.iframe[0].contentWindow;
                        Fw.call(options.closeHandler, null, [$(e.target), me, content, content ? content.App : null]);
                    });
                }
            }
            else{
                this.closableEl.hide();
            }
            //
            this.hasButtons = !!options.buttons;
            if(this.hasButtons){
                var btnEl;
                this.buttons = [];
                this.footer.children().remove();
                Fw.each(options.buttons, function(button){
                    Fw.applyIf(button, {
                        id: '',
                        cls: '',
                        dismiss: true
                    });
                    this.footer.append(this.btnTpl.render(button));
                    btnEl = this.footer.children('button:last');
                    this.buttons.push(btnEl);
                    if(button.handler){
                        btnEl.on('click', function(e){
                            var content = options.html ? null : me.iframe[0].contentWindow;
                            button.handler.call(button.scope || me, $(e.target), me, content, content ? content.App : null);
                        });
                    }
                }, this);
                this.footer.show();
            }
            else{
                this.footer.hide();
            }
            //
            this.remote = !!options.url;
            var maxHeight = this.el.height();
            var maxWidth = this.el.width();
            this.dialogHeight = options.height >= maxHeight ? maxHeight - 20 : options.height;
            this.dialogWidth = options.width >= maxWidth ? maxWidth - 20 : options.width;
            var bodyHeight = this.dialogHeight - 45 - (this.hasButtons ? 65 : 0);
            if(this.remote){
                this.remoteURL = Fw.isURL(options.url) ? options.url : Fw.getBasePath() + '/page' + options.url;
                this.body.hide();
                this.iframe.height(bodyHeight).width(this.dialogWidth).show().css('visibility', 'hidden');
                this.touch && this.touch.enable();
            }
            else{
                this.contentHTML = options.html || null;
                this.iframe.hide();
                this.body.html(this.contentHTML || '');
                this.body.height(bodyHeight - 20).width(this.dialogWidth - 20).show();
                this.touch && this.touch.disable();
            }
            this.content.width(this.dialogWidth);
            this.center();
        },
        /**
         * 显示后
         */
        onShow: function(){
            this.content.focus();
            this.fireEvent('show', this);
            //
            if(this.remote){
                if(this.iframe.attr('src') !== this.remoteURL){
                    Fw.defer(this.loadMask.show, 100, this.loadMask, [this.iframe]);
                    this.loaded = false;
                    this.iframe.attr('src', this.remoteURL);
                }
                else{
                    this.onLoadIframe();
                }
                this.iframe.css('visibility', 'visible');
            }
            this.hidden = false;
        },
        /**
         * 显示窗口
         */
        show: function(options){
            // options = options || this;
            if(this.hidden !== false){
                if(this.fireEvent('beforeshow', options, this) !== false){
                    this.el.modal({
                        keyboard: options.closable
                    });
                }
            }
            else{
                Fw.defer(function(){
                    if(this.fireEvent('beforeshow', options, this) !== false){
                        this.el.modal({
                            keyboard: options.closable
                        });
                    }
                }, 500, this);
            }
        },
        /**
         * 关闭窗口
         */
        close: function(){
            this.el.modal('hide');
        },
        /**
         * 窗口居中
         */
        center: function(){
            var top = (this.el.height() - this.dialogHeight) / 2;
            var left = (this.el.width() - this.dialogWidth) / 2;
            this.dialog.css({
                top: top,
                left: left
            });
        }
    });
    Fw.Window = new Fw.Modal();
    
    /**
     * 消息提示框
     */
    Fw.MessageBox = Fw.extend(Fw.Modal, {
        /**
         * 是否显示加载状态
         */
        loadMask: false,
        /**
         * 初始化事件
         */
        initEvents: function(){
            Fw.MessageBox.superclass.initEvents.call(this);
            //单击按钮时触发
            this.footer.on('click', 'button', Fw.bind(this.onBtnClick, this));
            //单击按钮时触发
            this.closableEl.on('click', Fw.bind(this.onBtnClick, this));
        },
        /**
         * 初始化HTML模版
         */
        initTpl: function(){
            Fw.MessageBox.superclass.initTpl.call(this);
            //
            var msgTpl = [
                '<div class="msgbox-body">',
                    '<div class="msgbox-text" style="${style}">$${msg}</div>',
                '</div>'
            ];
            this.msgTpl = Fw.template(msgTpl);
        },
        /**
         * 单击按钮时
         */
        onBtnClick: function(e){
            if(this.callback.fn){
                var btn = $(e.target);
                var type = btn.attr('optId') || btn.text();
                this.callback.fn.call(this.callback.scope || this, type, btn, this);
            }
        },
        /**
         * 信显示窗口
         */
        show: function(title, iconCls, msg, buttons, fn, scope){
            var options = {
                width: 400,
                height: 200,
                title: title,
                buttons: buttons
            };
            if(Fw.isObject(msg)){
                Fw.apply(options, msg);
            }
            else{
                options.msg = msg;
            }
            //
            var style = '';
            if(this.oldIconCls){
                this.body.removeClass('icon msgbox-icon ' + this.oldIconCls);
            }
            if(iconCls){
                this.body.addClass('icon msgbox-icon ' + iconCls);
                style = 'padding-left:70px;';
            }
            this.oldIconCls = iconCls;
            options.html = this.msgTpl.render({
                style: style,
                msg: options.msg
            });
            //
            this.callback = {
                fn: fn,
                scope: scope
            };
            //
            Fw.MessageBox.superclass.show.call(this, options);
        },
        /**
         * 信息
         */
        info: function(msg, fn, scope){
            var buttons = [
                {id: 'ok', text: '确定', cls: 'btn-primary'}
            ];
            this.show('信息','icon-info', msg, buttons, fn, scope);
        },
        /**
         * 错误
         */
        error: function(msg, fn, scope){
            var buttons = [
                {id: 'ok', text: '确定', cls: 'btn-primary'}
            ];
            this.show('错误','icon-error', msg, buttons, fn, scope);
        },
        /**
         * 询问
         */
        quest: function(msg, fn, scope){
            var buttons = [
                {id: 'yes', text: '确定', cls: 'btn-primary'},
                {id: 'no', text: '取消', cls: 'btn-default'}
            ];
            if(!Fw.isObject(msg)){
                msg = {
                    msg: msg
                };
            }
            msg.closable = false;
            this.show('问题','icon-question', msg, buttons, fn, scope);
        },
        /**
         * 警告
         */
        warn: function(msg, fn, scope){
            var buttons = [
                {id: 'ok', text: '确定', cls: 'btn-primary'}
            ];
            this.show('警告','icon-warning', msg, buttons, fn, scope);
        }
    });
    Fw.Msg = new Fw.MessageBox();
    
    /**
     * 弹出窗口底层依赖
     */
    +function ($) {
      'use strict';
    
      // MODAL CLASS DEFINITION
      // ======================
    
      var Modal = function (element, options) {
        this.options        = options
        this.$body          = $(document.body)
        this.$element       = $(element)
        this.$backdrop      =
        this.isShown        = null
        this.scrollbarWidth = 0
    
        if (this.options.remote) {
          this.$element
            .find('.modal-content')
            .load(this.options.remote, $.proxy(function () {
              this.$element.trigger('loaded.bs.modal')
            }, this))
        }
      }
    
      Modal.VERSION  = '3.2.0'
    
      Modal.DEFAULTS = {
        backdrop: true,
        keyboard: true,
        show: true
      }
    
      Modal.prototype.toggle = function (_relatedTarget) {
        return this.isShown ? this.hide() : this.show(_relatedTarget)
      }
    
      Modal.prototype.show = function (_relatedTarget) {
        var that = this
        var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
    
        this.$element.trigger(e)
    
        if (this.isShown || e.isDefaultPrevented()) return
    
        this.isShown = true
    
        this.checkScrollbar()
        this.$body.addClass('modal-open')
    
        this.setScrollbar()
        this.escape()
    
        this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
    
        this.backdrop(function () {
          var transition = $.support.transition && that.$element.hasClass('fade')
    
          if (!that.$element.parent().length) {
            that.$element.appendTo(that.$body) // don't move modals dom position
          }
    
          that.$element
            .show()
            .scrollTop(0)
    
          if (transition) {
            that.$element[0].offsetWidth // force reflow
          }
    
          that.$element
            .addClass('in')
            .attr('aria-hidden', false)
    
          that.enforceFocus()
    
          var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
    
          transition ?
            that.$element.find('.modal-dialog') // wait for modal to slide in
              .one('bsTransitionEnd', function () {
                that.$element.trigger('focus').trigger(e)
              })
              .emulateTransitionEnd(300) :
            that.$element.trigger('focus').trigger(e)
        })
      }
    
      Modal.prototype.hide = function (e) {
        if (e) e.preventDefault()
    
        e = $.Event('hide.bs.modal')
    
        this.$element.trigger(e)
    
        if (!this.isShown || e.isDefaultPrevented()) return
    
        this.isShown = false
    
        this.$body.removeClass('modal-open')
    
        this.resetScrollbar()
        this.escape()
    
        $(document).off('focusin.bs.modal')
    
        this.$element
          .removeClass('in')
          .attr('aria-hidden', true)
          .off('click.dismiss.bs.modal')
    
        $.support.transition && this.$element.hasClass('fade') ?
          this.$element
            .one('bsTransitionEnd', $.proxy(this.hideModal, this))
            .emulateTransitionEnd(300) :
          this.hideModal()
      }
    
      Modal.prototype.enforceFocus = function () {
        $(document)
          .off('focusin.bs.modal') // guard against infinite focus loop
          .on('focusin.bs.modal', $.proxy(function (e) {
            if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
              this.$element.trigger('focus')
            }
          }, this))
      }
    
      Modal.prototype.escape = function () {
        if (this.isShown && this.options.keyboard) {
          this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
            e.which == 27 && this.hide()
          }, this))
        } else if (!this.isShown) {
          this.$element.off('keyup.dismiss.bs.modal')
        }
      }
    
      Modal.prototype.hideModal = function () {
        var that = this
        this.$element.hide()
        this.backdrop(function () {
          that.$element.trigger('hidden.bs.modal')
        })
      }
    
      Modal.prototype.removeBackdrop = function () {
        this.$backdrop && this.$backdrop.remove()
        this.$backdrop = null
      }
    
      Modal.prototype.backdrop = function (callback) {
        var that = this
        var animate = this.$element.hasClass('fade') ? 'fade' : ''
    
        if (this.isShown && this.options.backdrop) {
          var doAnimate = $.support.transition && animate
    
          this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
            .appendTo(this.$body)
    
          //davi-
          // this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
            // if (e.target !== e.currentTarget) return
            // this.options.backdrop == 'static'
              // ? this.$element[0].focus.call(this.$element[0])
              // : this.hide.call(this)
          // }, this))
          //end
          
          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
    
          this.$backdrop.addClass('in')
    
          if (!callback) return
    
          doAnimate ?
            this.$backdrop
              .one('bsTransitionEnd', callback)
              .emulateTransitionEnd(150) :
            callback()
    
        } else if (!this.isShown && this.$backdrop) {
          this.$backdrop.removeClass('in')
    
          var callbackRemove = function () {
            that.removeBackdrop()
            callback && callback()
          }
          $.support.transition && this.$element.hasClass('fade') ?
            this.$backdrop
              .one('bsTransitionEnd', callbackRemove)
              .emulateTransitionEnd(150) :
            callbackRemove()
    
        } else if (callback) {
          callback()
        }
      }
    
      Modal.prototype.checkScrollbar = function () {
        if (document.body.clientWidth >= window.innerWidth) return
        this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar()
      }
    
      Modal.prototype.setScrollbar = function () {
        var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
        if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
      }
    
      Modal.prototype.resetScrollbar = function () {
        this.$body.css('padding-right', '')
      }
    
      Modal.prototype.measureScrollbar = function () { // thx walsh
        var scrollDiv = document.createElement('div')
        scrollDiv.className = 'modal-scrollbar-measure'
        this.$body.append(scrollDiv)
        var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
        this.$body[0].removeChild(scrollDiv)
        return scrollbarWidth
      }
    
    
      // MODAL PLUGIN DEFINITION
      // =======================
    
      function Plugin(option, _relatedTarget) {
        return this.each(function () {
          var $this   = $(this)
          var data    = $this.data('bs.modal')
          var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
    
          if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
          if (typeof option == 'string') data[option](_relatedTarget)
          else if (options.show) data.show(_relatedTarget)
        })
      }
    
      var old = $.fn.modal
    
      $.fn.modal             = Plugin
      $.fn.modal.Constructor = Modal
    
    
      // MODAL NO CONFLICT
      // =================
    
      $.fn.modal.noConflict = function () {
        $.fn.modal = old
        return this
      }
    
    
      // MODAL DATA-API
      // ==============
    
      $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
        var $this   = $(this)
        var href    = $this.attr('href')
        var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
        var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
    
        if ($this.is('a')) e.preventDefault()
    
        $target.one('show.bs.modal', function (showEvent) {
          if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
          $target.one('hidden.bs.modal', function () {
            $this.is(':visible') && $this.trigger('focus')
          })
        })
        Plugin.call($target, option, this)
      })
    
    }(jQuery);
}
